/*
 * @FilePath: /gis-platform/src/views/irs-map/config/config.js
 * @Author: 张文鑫
 * @Date: 2024-12-02 17:33:41
 * @Description: 地图配置及操作逻辑
 */
// 导入模块
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Style, Text, Fill, Stroke } from "ol/style";
import axios from "axios";
import { convertTestJson } from "@/utils/index";
import GeoJSON from "ol/format/GeoJSON";
import TileLayer from "ol/layer/Tile";
import WMTS from "ol/source/WMTS";
import WMTSTileGrid from "ol/tilegrid/WMTS";
import { get as getProjection } from "ol/proj";
import { getTopLeft, getWidth } from "ol/extent";
import CryptoJS from "crypto-js";

// =============== JWT 认证相关 ===============
/**
 * Base64 URL 编码函数
 * @param {*} str 待编码的字符串
 * @returns {string} 编码后的字符串
 */
function base64UrlEncode(str) {
  const encodedSource = CryptoJS.enc.Base64.stringify(str);
  return encodedSource.replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
}

/**
 * 生成JWT令牌
 * @param {string} accessKey - 访问密钥
 * @param {string} secretKey - 秘密密钥
 * @returns {string} JWT令牌
 */
function generateJWT(accessKey, secretKey) {
  const header = JSON.stringify({ alg: "HS256", typ: "JWT" });
  const payload = JSON.stringify({
    key: accessKey,
    exp: new Date().setHours(new Date().getHours() + 1),
  });

  const beforeSign =
    base64UrlEncode(CryptoJS.enc.Utf8.parse(header)) + "." + base64UrlEncode(CryptoJS.enc.Utf8.parse(payload));
  const signature = CryptoJS.HmacSHA256(beforeSign, secretKey);
  return beforeSign + "." + base64UrlEncode(signature);
}

// 密钥配置 (后端实现时应移除)
const CONFIG = {
  accessKey: "BCDSGA_9ecfbd973839a52fcb943b28f661cd0f",
  secretKey: "BCDSGS_26eb426798a2919a421dde6f482f7100",
  mapUrls: {
    vector: "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220315000001/services/wmts/emap/default/oss",
    image: "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220406000002/services/wmts/imgmap/default/oss",
  },
  apiUrls: {
    county: "https://api.gis.doits.cn/sxmap/data/county.json",
    town: "https://api.gis.doits.cn/sxmap/data/town.json",
    village: "https://api.gis.doits.cn/service/getBQueryResult",
  },
};

// 生成JWT令牌
const jwtToken = generateJWT(CONFIG.accessKey, CONFIG.secretKey);

/**
 * 获取认证URL
 * @param {string} baseUrl - 基础URL
 * @returns {string} 添加认证信息的URL
 */
const getAuthUrl = (baseUrl) => {
  return baseUrl + "?jwt=" + jwtToken + "&x-bg-auth-type=jwt_auth";
};

// =============== 地图投影和瓦片网格配置 ===============
const projection = getProjection("EPSG:4326");
const projectionExtent = projection.getExtent();
const tileSize = getWidth(projectionExtent) / 256;

// 生成分辨率和矩阵ID数组
const generateResolutionsAndMatrixIds = (levels = 20) => {
  const resolutions = new Array(levels);
  const matrixIds = new Array(levels);

  for (let z = 0; z < levels; ++z) {
    resolutions[z] = tileSize / Math.pow(2, z);
    matrixIds[z] = z;
  }

  return { resolutions, matrixIds };
};

const { resolutions, matrixIds } = generateResolutionsAndMatrixIds();

// =============== 图层创建 ===============
/**
 * 创建WMTS图层
 * @param {string} url - 服务URL
 * @param {string} layer - 图层名称
 * @returns {TileLayer} WMTS图层
 */
function createWMTSLayer(url, layer = "emap") {
  return new TileLayer({
    opacity: 1,
    source: new WMTS({
      url: getAuthUrl(url),
      layer: layer,
      matrixSet: "EPSG:4326",
      format: "image/png",
      projection: projection,
      tileGrid: new WMTSTileGrid({
        origin: getTopLeft(projectionExtent),
        resolutions: resolutions,
        matrixIds: matrixIds,
      }),
      style: "default",
      wrapX: true,
    }),
  });
}

// 全局数据存储
let townData = { type: "FeatureCollection", features: [] };
let hoveredFeature = null;

// 创建基础图层
export const vec_wLayer = createWMTSLayer(CONFIG.mapUrls.vector);
export const img_wLayer = createWMTSLayer(CONFIG.mapUrls.image);

// 创建一个空的矢量图层
const vectorSource = new VectorSource();
export const vectorLayer = new VectorLayer({
  source: vectorSource,
  zIndex: 3, // 确保在所有图层最上层
});

// =============== 样式工具函数 ===============
/**
 * 创建文本样式
 * @param {string} text - 显示文本
 * @param {object} options - 文本样式选项
 * @returns {Text} 文本样式对象
 */
function createTextStyle(
  text,
  { isBold = false, fontSize = 12, color = "#ffffff", strokeColor = "#003366", offsetY = -10 } = {}
) {
  return new Text({
    text: text,
    font: `${isBold ? "bold " : ""}${fontSize}px sans-serif`,
    fill: new Fill({ color }),
    stroke: new Stroke({
      color: strokeColor,
      width: 3,
    }),
    offsetY,
  });
}

/**
 * 创建区域样式
 * @param {object} options - 样式选项
 * @returns {Style} 样式对象
 */
function createAreaStyle({ name, isHovered = false, level = "county", hasGrid = false }) {
  // 根据级别和网格配置不同的颜色
  let fillColor, strokeColor, strokeWidth, textStrokeColor, fontSize, textOffsetY;

  if (level === "county") {
    fillColor = isHovered ? "rgba(0, 51, 102, 0.6)" : "rgba(0, 51, 102, 0.4)";
    strokeColor = "#0066cc";
    strokeWidth = isHovered ? 3 : 2;
    textStrokeColor = "#003366";
    fontSize = isHovered ? 14 : 12;
    textOffsetY = -15;
  } else if (level === "town") {
    fillColor = hasGrid ? "rgba(75, 0, 130, 0.4)" : "rgba(0, 128, 255, 0.4)";
    strokeColor = hasGrid ? "#8a2be2" : "#0099ff";
    strokeWidth = 2;
    textStrokeColor = hasGrid ? "#4b0082" : "#004080";
    fontSize = 12;
    textOffsetY = -10;
  } else if (level === "village") {
    fillColor = hasGrid ? "rgba(138, 43, 226, 0.4)" : "rgba(102, 178, 255, 0.4)";
    strokeColor = hasGrid ? "#9370db" : "#66b2ff";
    strokeWidth = 1;
    textStrokeColor = hasGrid ? "#4b0082" : "#0066cc";
    fontSize = 12;
    textOffsetY = -10;
  }

  return new Style({
    fill: new Fill({ color: fillColor }),
    stroke: new Stroke({
      color: strokeColor,
      width: strokeWidth,
    }),
    text: createTextStyle(name, {
      isBold: isHovered,
      fontSize,
      strokeColor: textStrokeColor,
      offsetY: textOffsetY,
    }),
  });
}

/**
 * 创建透明样式 (用于隐藏区域但保留边框和文本)
 * @param {object} options - 样式选项
 * @returns {Style} 样式对象
 */
function createTransparentStyle({ name, level = "county", hasGrid = false }) {
  let strokeColor, textStrokeColor, textOffsetY;

  if (level === "county") {
    strokeColor = "#0066cc";
    textStrokeColor = "#003366";
    textOffsetY = -15;
  } else if (level === "town") {
    strokeColor = "#004080";
    textStrokeColor = "#001a33";
    textOffsetY = -10;
  } else if (level === "village") {
    strokeColor = hasGrid ? "#9370db" : "#66b2ff";
    textStrokeColor = hasGrid ? "#4b0082" : "#004d99";
    textOffsetY = -10;
  }

  return new Style({
    fill: new Fill({
      // 如果是网格区域则保留轻微的填充色
      color: hasGrid && level === "village" ? "rgba(138, 43, 226, 0.2)" : "rgba(0, 0, 0, 0)",
    }),
    stroke: new Stroke({
      color: strokeColor,
      width: 1,
    }),
    text: createTextStyle(name, {
      fontSize: 12,
      strokeColor: textStrokeColor,
      offsetY: textOffsetY,
    }),
  });
}

/**
 * 创建高亮样式 (用于当前选中的区域)
 * @param {object} options - 样式选项
 * @returns {Style} 样式对象
 */
function createHighlightStyle({ name, level = "county", hasGrid = false }) {
  let fillColor, strokeColor, textStrokeColor;

  if (level === "county") {
    fillColor = "rgba(0, 51, 102, 0.4)";
    strokeColor = "#0066cc";
    textStrokeColor = "#003366";
  } else if (level === "town") {
    // 镇级无需实现此样式
    fillColor = "rgba(0, 0, 0, 0)";
    strokeColor = "#004080";
    textStrokeColor = "#001a33";
  } else if (level === "village") {
    fillColor = hasGrid ? "rgba(138, 43, 226, 0.3)" : "rgba(0, 0, 0, 0)";
    strokeColor = hasGrid ? "#8a2be2" : "#0066cc";
    textStrokeColor = hasGrid ? "#4b0082" : "#004d99";
  }

  return new Style({
    fill: new Fill({ color: fillColor }),
    stroke: new Stroke({
      color: strokeColor,
      width: 3,
    }),
    text: createTextStyle(name, {
      isBold: true,
      fontSize: 14,
      strokeColor: textStrokeColor,
      offsetY: level === "county" ? -15 : -10,
    }),
  });
}

// =============== 图层创建函数 ===============
/**
 * 创建区县图层
 * @returns {Promise<VectorLayer>} 区县矢量图层
 */
export async function createDistrictLayer() {
  try {
    const response = await axios.get(CONFIG.apiUrls.county, {
      params: { v: "2024102301" },
    });
    const geoJsonData = convertTestJson(response.data);

    // 设置特性级别
    geoJsonData.features.forEach((feature) => {
      feature.properties.level = "county";
    });

    return new VectorLayer({
      source: new VectorSource({
        features: new GeoJSON().readFeatures(geoJsonData),
      }),
      style: function (feature) {
        return createAreaStyle({
          name: feature.get("name"),
          isHovered: feature === hoveredFeature,
          level: "county",
        });
      },
      zIndex: 2,
    });
  } catch (error) {
    console.error("获取区县数据失败:", error);
    return null;
  }
}

/**
 * 创建镇级区域图层
 * @param {string} pcode - 父级编码
 * @returns {Promise<VectorLayer>} 镇级矢量图层
 */
async function createTownLayer(pcode) {
  try {
    let geoJsonData = { type: "FeatureCollection", features: [] };

    // 如果还没有加载镇数据，先获取全部数据
    if (townData.features.length === 0) {
      const response = await axios.get(CONFIG.apiUrls.town);
      townData = convertTestJson(response.data);

      // 设置特性级别
      townData.features.forEach((feature) => {
        feature.properties.level = "town";
      });
    }

    // 筛选特定父级编码的镇
    geoJsonData.features = townData.features.filter((feature) => {
      return feature.properties.pcode == pcode;
    });

    return new VectorLayer({
      source: new VectorSource({
        features: new GeoJSON().readFeatures(geoJsonData),
      }),
      style: function (feature) {
        const name = feature.get("name");
        const hasGrid = name.includes("网格");

        return createAreaStyle({
          name,
          level: "town",
          hasGrid,
        });
      },
      zIndex: 2.5,
      visible: true,
    });
  } catch (error) {
    console.error("获取镇级数据失败:", error);
    return null;
  }
}

/**
 * 创建村级区域图层
 * @param {string} bh - 编号
 * @returns {Promise<VectorLayer>} 村级矢量图层
 */
async function createVillageLayer(bh) {
  try {
    const response = await axios.get(CONFIG.apiUrls.village, {
      params: {
        appid: "SXZZB",
        name: "queryVillageNArea",
        pcode: bh,
      },
    });

    if (!response.data?.data) {
      console.warn("未获取到村级数据");
      return null;
    }

    const geoJsonData = convertTestJson(response.data);

    // 设置特性级别
    geoJsonData.features.forEach((feature) => {
      feature.properties.level = "village";
    });

    return new VectorLayer({
      source: new VectorSource({
        features: new GeoJSON().readFeatures(geoJsonData),
      }),
      style: function (feature) {
        const name = feature.get("name");
        const hasGrid = name.includes("网格");

        return createAreaStyle({
          name,
          level: "village",
          hasGrid,
        });
      },
      zIndex: 3,
    });
  } catch (error) {
    console.error("获取村级数据失败:", error);
    return null;
  }
}

// =============== 事件处理和交互逻辑 ===============
/**
 * 添加地图交互和缩放监听
 * @param {Map} map - OpenLayers地图实例
 * @returns {Function} 清理函数
 */
export function addZoomListener(map) {
  let townLayer = null;
  let villageLayer = null;

  // ===== 悬停效果处理 =====
  map.on("pointermove", (evt) => {
    const pixel = map.getEventPixel(evt.originalEvent);

    // 更改鼠标样式
    const hit = map.hasFeatureAtPixel(pixel);
    map.getTargetElement().style.cursor = hit ? "pointer" : "";

    // 获取鼠标下的特性
    const feature = map.forEachFeatureAtPixel(pixel, (feature) => feature);

    // 只处理区县级别的悬停效果
    if (feature && feature.getProperties().level === "county") {
      if (hoveredFeature !== feature) {
        hoveredFeature = feature;
        // 触发图层重绘
        map
          .getLayers()
          .getArray()
          .forEach((layer) => {
            if (layer instanceof VectorLayer && layer.getZIndex() === 2) {
              layer.changed();
            }
          });
      }
    } else if (hoveredFeature && hoveredFeature.getProperties().level === "county") {
      hoveredFeature = null;
      // 触发图层重绘
      map
        .getLayers()
        .getArray()
        .forEach((layer) => {
          if (layer instanceof VectorLayer && layer.getZIndex() === 2) {
            layer.changed();
          }
        });
    }
  });

  // ===== 视图变化处理 =====
  map.on("moveend", async () => {
    const view = map.getView();
    const zoom = view.getZoom();
    const center = view.getCenter();

    // 获取中心点所在的特性
    const feature = map.forEachFeatureAtPixel(map.getPixelFromCoordinate(center), (feature) => feature);

    if (!feature) {
      // 如果缩小到看不到任何区域，清除图层
      if (zoom < 10) {
        if (townLayer) {
          map.removeLayer(townLayer);
          townLayer = null;
        }
        if (villageLayer) {
          map.removeLayer(villageLayer);
          villageLayer = null;
        }
      }
      return;
    }

    // 根据缩放级别和特性类型可以在这里添加更多逻辑
  });

  // ===== 点击事件处理 =====
  map.on("click", async (evt) => {
    const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature);
    if (!feature) return;

    const geometry = feature.getGeometry();
    const extent = geometry.getExtent();
    const view = map.getView();
    const zoom = view.getZoom();

    // 点击区县
    if (feature.getProperties().level === "county") {
      handleCountyClick(map, feature, extent, view, townLayer, villageLayer).then((result) => {
        townLayer = result.townLayer;
        villageLayer = result.villageLayer;
      });
    }
    // 点击乡镇
    else if (feature.getProperties().level === "town") {
      handleTownClick(map, feature, extent, view, townLayer, villageLayer).then((result) => {
        villageLayer = result.villageLayer;
      });
    }
    // 点击村级
    else if (feature.getProperties().level === "village" && zoom < 14) {
      handleVillageClick(map, feature, extent, view, villageLayer);
    }
    // 缩小时恢复所有图层
    else if (zoom < 10) {
      resetLayers(map, townLayer, villageLayer).then((result) => {
        townLayer = result.townLayer;
        villageLayer = result.villageLayer;
      });
    }
  });

  // 在组件销毁时清理
  return () => {
    if (townLayer) {
      map.removeLayer(townLayer);
    }
    if (villageLayer) {
      map.removeLayer(villageLayer);
    }
  };
}

/**
 * 处理区县点击事件
 * @param {Map} map - 地图实例
 * @param {Feature} feature - 点击的特性
 * @param {Array} extent - 边界范围
 * @param {View} view - 视图对象
 * @param {Layer} townLayer - 镇图层
 * @param {Layer} villageLayer - 村图层
 * @returns {Promise<Object>} 更新后的图层
 */
async function handleCountyClick(map, feature, extent, view, townLayer, villageLayer) {
  // 放大并移动到点击的区县
  view.animate({
    center: [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2],
    zoom: 10,
    duration: 1000,
  });

  // 查找区县图层
  const districtLayer = map
    .getLayers()
    .getArray()
    .find((layer) => layer instanceof VectorLayer && layer.getZIndex() === 2);

  // 设置区县样式
  if (districtLayer) {
    districtLayer
      .getSource()
      .getFeatures()
      .forEach((f) => {
        if (f !== feature) {
          // 为其他区县设置透明样式
          f.setStyle(
            createTransparentStyle({
              name: f.get("name"),
              level: "county",
            })
          );
        } else {
          // 为当前区县设置高亮样式
          f.setStyle(
            createHighlightStyle({
              name: f.get("name"),
              level: "county",
            })
          );
        }
      });
  }

  // 移除现有图层
  if (townLayer) {
    map.removeLayer(townLayer);
    townLayer = null;
  }
  if (villageLayer) {
    map.removeLayer(villageLayer);
    villageLayer = null;
  }

  // 加载该区县的乡镇图层
  townLayer = await createTownLayer(feature.getProperties().bh);
  if (townLayer) {
    townLayer.set("bh", feature.getProperties().bh);
    map.addLayer(townLayer);
    townLayer.setVisible(true);
  }

  return { townLayer, villageLayer };
}

/**
 * 处理镇点击事件
 * @param {Map} map - 地图实例
 * @param {Feature} feature - 点击的特性
 * @param {Array} extent - 边界范围
 * @param {View} view - 视图对象
 * @param {Layer} townLayer - 镇图层
 * @param {Layer} villageLayer - 村图层
 * @returns {Promise<Object>} 更新后的图层
 */
async function handleTownClick(map, feature, extent, view, townLayer, villageLayer) {
  // 放大并移动到点击的乡镇
  view.animate({
    center: [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2],
    zoom: 12,
    duration: 1000,
  });

  // 隐藏区县图层
  map
    .getLayers()
    .getArray()
    .forEach((layer) => {
      if (layer instanceof VectorLayer && layer.getZIndex() === 2) {
        layer.setVisible(false);
      }
    });

  // 隐藏其他乡镇，只显示当前乡镇
  if (townLayer) {
    townLayer
      .getSource()
      .getFeatures()
      .forEach((f) => {
        if (f !== feature) {
          // 为其他乡镇设置透明样式
          f.setStyle(
            createTransparentStyle({
              name: f.get("name"),
              level: "town",
            })
          );
        }
      });
  }

  // 加载该乡镇的村级图层
  const bh = feature.getProperties().bh;
  if (bh && (!villageLayer || villageLayer.get("bh") !== bh)) {
    if (villageLayer) {
      map.removeLayer(villageLayer);
    }

    villageLayer = await createVillageLayer(bh);
    if (villageLayer) {
      villageLayer.set("bh", bh);
      map.addLayer(villageLayer);
    }
  }

  return { villageLayer };
}

/**
 * 处理村点击事件
 * @param {Map} map - 地图实例
 * @param {Feature} feature - 点击的特性
 * @param {Array} extent - 边界范围
 * @param {View} view - 视图对象
 * @param {Layer} villageLayer - 村图层
 */
function handleVillageClick(map, feature, extent, view, villageLayer) {
  // 放大并移动到点击的村
  view.animate({
    center: [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2],
    zoom: 15,
    duration: 1000,
  });

  // 隐藏其他村，只显示当前村的边框
  if (villageLayer) {
    villageLayer
      .getSource()
      .getFeatures()
      .forEach((f) => {
        const name = f.get("name");
        const hasGrid = name.includes("网格");

        if (f !== feature) {
          // 为其他村设置透明样式
          f.setStyle(
            createTransparentStyle({
              name,
              level: "village",
              hasGrid,
            })
          );
        } else {
          // 为当前村设置高亮样式
          f.setStyle(
            createHighlightStyle({
              name,
              level: "village",
              hasGrid,
            })
          );
        }
      });
  }
}

/**
 * 重置所有图层到初始状态
 * @param {Map} map - 地图实例
 * @param {Layer} townLayer - 镇图层
 * @param {Layer} villageLayer - 村图层
 * @returns {Promise<Object>} 更新后的图层
 */
async function resetLayers(map, townLayer, villageLayer) {
  // 恢复区县图层可见性
  map
    .getLayers()
    .getArray()
    .forEach((layer) => {
      if (layer instanceof VectorLayer && layer.getZIndex() === 2) {
        layer.setVisible(true);
      }
    });

  // 移除镇和村图层
  if (townLayer) {
    map.removeLayer(townLayer);
    townLayer = null;
  }
  if (villageLayer) {
    map.removeLayer(villageLayer);
    villageLayer = null;
  }

  return { townLayer, villageLayer };
}
